Skip to content

feat: end-to-end job orchestration, realtime workflow tracking & n8n integration#1

Merged
aintnier merged 10 commits intomainfrom
fix/n8n-workflow-optimization
Sep 4, 2025
Merged

feat: end-to-end job orchestration, realtime workflow tracking & n8n integration#1
aintnier merged 10 commits intomainfrom
fix/n8n-workflow-optimization

Conversation

@aintnier
Copy link
Copy Markdown
Owner

@aintnier aintnier commented Aug 19, 2025

feat: end-to-end job orchestration, realtime workflow tracking & n8n integration

High-level

  • Introduced background “job” model with granular “job_steps” to orchestrate
    multi-phase resource processing (duplicates check → content type detection →
    content extraction → AI processing → database save).
  • Added robust Supabase Edge Functions for job lifecycle + step updates with
    automatic status aggregation (pending → running → completed/failed) and
    timestamp management.
  • Integrated n8n workflow to drive all phases via HTTP calls to Edge Functions,
    including error handler path, branch-specific step outputs and execution ID
    correlation.
  • Implemented realtime UI notifications (jobs + job_steps) with progress
    toasts and English localization; removed duplicate local job creation.
  • Hardened auth (service role detection, user resolution) and standardized
    request/response schema, headers and metadata fields.

Database & Realtime

  • Added tables: jobs (status, workflow_execution_id, resource_id, timestamps,
    metadata) and job_steps (per-step status, output_data/metadata, ordering).
  • Added publication / replication setup so jobs & job_steps emit realtime
    change events used by frontend toasts.
  • Enforced consistent terminal rules: job auto-finalizes when all steps
    terminal; direct skip to terminal sets started_at defensively.

Edge Functions

  • New/extended functions: create-job, update-job-step, get-job-status,
    (existing resource CRUD adapted to cooperate with job pipeline).
  • Added service role vs user JWT logic (no leaking privileges for user tokens).
  • Accept workflow_execution_id, resource_id, metadata; validate and persist.
  • Auto-aggregation in update-job-step computes job status + timestamps and
    guards against partial step waves.
  • Uniform error envelopes with clear 4xx vs 5xx mapping.

Frontend

  • Added useJobNotifications hook subscribing to jobs + job_steps realtime
    channels; progress computation (completed/skipped vs total) with percentage.
  • Toast taxonomy: workflow started / running / step completed (with next step
    hint) / workflow completed / workflow failed (destructive).
  • Removed redundant client-side job creation to eliminate “ghost” jobs.
  • Local job cache updating on INSERT/UPDATE ensures fast UI reflection.

n8n Workflow

  • Inserted HTTP node to create job early; passed workflow_execution_id and
    initial steps definition for deterministic ordering.
  • Added per-branch step update nodes (YouTube vs Article paths) with unified
    step_name set to one semantic step per phase; avoided name collisions in
    same branch.
  • Provided rich output_data payloads: detection results, transcript metrics,
    extraction lengths, AI model info, tags/key points counts, saved resource id.
  • Fixed malformed JSON issues (trailing commas, missing commas, wrong headers)
    by migrating bodies toward expression-object style or corrected raw JSON.
  • Standardized Authorization header (removed erroneous "=Authorization").
  • Global error handler node posts failed step update with contextual message,
    guarded when job_id is missing.

Notifications & UX

  • Progress toasts now show “Step X completed (n/total - p%). Currently running:
    ” enabling real-time mental model of pipeline.
  • Failure surfaces first failing step context; success summarizes completion.

Security & Robustness

  • Service role usage isolated to n8n; user-specific read paths rely on user_id
    filtering plus realtime channel filters.
  • Sanitized error messages (length bounded) to avoid oversized payloads.
  • Fallback timestamp logic ensures analytics consistency even on fast skips.

Use Cases (illustrative)

  1. New YouTube link:
    • Job created (toast “Workflow Started”).
    • Steps fire sequentially: duplicates check (fast), content type detection,
      content extraction (transcript), AI processing (LLM summary), database save.
    • Each completion triggers progress toast; final step auto-finalizes job and
      emits “Workflow Completed”.
  2. New article URL:
    • Branch switches to article extraction path; similar chain with site scrape
      • AI summary; database save links resource_id back into job.
  3. Duplicate link:
    • Duplicates step returns existing resource_id; job may short-circuit or
      continue based on config; UI still shows precise failure or skip outcome.
  4. Failure scenario (e.g. bad scraping / LLM timeout):
    • Errant step update posts status=failed; backend auto-finalizes job;
      toast “Workflow Failed” with truncated root cause.

Developer Improvements

  • Single source of truth for progress logic and lifecycle in backend functions.
  • Clean separation: n8n orchestrates, backend enforces correctness & integrity.
  • Easier observability: job_steps output_data now captures branch-specific
    metrics for later analytics (model usage, content lengths, detection types).

Follow-ups (not included)

  • Move plaintext API keys to secure n8n credentials everywhere.
  • Add running (pre-completion) step updates for richer streaming progress.
  • Introduce retry / backoff strategy inside update-job-step for transient LLM
    or scraping errors.
  • Optional metrics endpoint for aggregated per-user processing stats.

Summary by Sourcery

Add end-to-end job orchestration with granular job steps, backed by new Supabase tables and edge functions, integrated into n8n workflows, and surfaced in the UI via real-time notifications and a JobMonitor component.

New Features:

  • Add job and job_steps tables to support multi-phase resource processing orchestration
  • Introduce create-job, update-job-step, and get-job-status Supabase Edge Functions with automatic status aggregation
  • Integrate n8n workflows to drive each processing phase via HTTP calls to edge functions with execution ID correlation and error handling
  • Implement real-time workflow tracking in the UI using useJobNotifications hook and JobMonitor component with progress bars and toast notifications
  • Add JobService client and TypeScript types for invoking edge functions and managing job entities

Enhancements:

  • Harden authentication by distinguishing between user JWTs and service-role tokens and enforcing access controls
  • Standardize request/response formats, headers, and metadata across edge functions
  • Remove redundant frontend job creation to eliminate ghost jobs and centralize orchestration
  • Centralize progress computation in backend functions and emit realtime change events for UI updates
  • Add Radix Progress component for visualizing job progress in the frontend

Build:

  • Enable new edge functions in supabase/config.toml
  • Add @radix-ui/react-progress dependency in frontend package.json

Documentation:

  • Add n8n-job-notifications-integration.md to guide users on connecting n8n workflows with the job notification system

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Aug 19, 2025

Reviewer's Guide

This PR introduces a comprehensive job orchestration framework by defining a jobs/job_steps model in Supabase, implementing secure Edge Functions to manage job lifecycles and aggregate step statuses, integrating n8n workflows for deterministic phase execution, and extending the frontend with realtime subscriptions, toast notifications, and a dedicated JobMonitor component to visualize progress.

Sequence diagram for n8n workflow orchestrating job creation and step updates via Edge Functions

sequenceDiagram
  actor User
  participant Frontend
  participant n8n
  participant EdgeFunctions
  participant SupabaseDB

  User->>Frontend: Initiates resource processing
  Frontend->>n8n: Triggers workflow (webhook)
  n8n->>EdgeFunctions: POST /create-job (with steps)
  EdgeFunctions->>SupabaseDB: Insert job and job_steps
  EdgeFunctions-->>n8n: Job created response
  n8n->>EdgeFunctions: POST /update-job-step (step status)
  EdgeFunctions->>SupabaseDB: Update job_steps, aggregate job status
  EdgeFunctions-->>n8n: Step update response
  n8n->>EdgeFunctions: Repeat for each step (branching as needed)
  EdgeFunctions->>SupabaseDB: Finalize job when all steps terminal
  SupabaseDB-->>Frontend: Emit realtime change events
  Frontend->>User: Show progress toasts and JobMonitor updates
Loading

Entity relationship diagram for jobs and job_steps tables

erDiagram
  JOBS {
    string id PK
    string user_id
    string workflow_name
    string workflow_execution_id
    string status
    string created_at
    string started_at
    string completed_at
    string error_message
    json metadata
    int resource_id
  }
  JOB_STEPS {
    string id PK
    string job_id FK
    string step_name
    string step_type
    string status
    string started_at
    string completed_at
    string error_message
    json output_data
    int step_order
    json metadata
  }
  JOBS ||--o{ JOB_STEPS : has
Loading

Class diagram for Job, JobStep, JobWithSteps, and JobNotification types

classDiagram
  class Job {
    string id
    string user_id
    string workflow_name
    string workflow_execution_id
    JobStatus status
    string created_at
    string started_at
    string completed_at
    string error_message
    json metadata
    int resource_id
  }
  class JobStep {
    string id
    string job_id
    string step_name
    string step_type
    JobStepStatus status
    string started_at
    string completed_at
    string error_message
    json output_data
    int step_order
    json metadata
  }
  class JobWithSteps {
    JobStep[] steps
  }
  class JobNotification {
    string type
    Job job
    JobStep step
    string message
  }
  JobWithSteps --|> Job
  JobWithSteps "1" o-- "many" JobStep
  JobNotification --> Job
  JobNotification --> JobStep
Loading

File-Level Changes

Change Details Files
Configure and register new Supabase Edge Functions
  • Enabled create-job, update-job-step and get-job-status functions in supabase/config.toml
  • Set verify_jwt and import_map for each function
  • Specified TypeScript entrypoints for all functions
supabase/config.toml
Implement create-job, update-job-step and get-job-status Edge Functions
  • create-job: service-role vs user JWT handling, user resolution, insert job and its steps
  • update-job-step: status transition, timestamp management, output_data/metadata storage and auto-aggregate parent job status
  • get-job-status: fetch user-scoped jobs and steps, support optional job_id, status and limit params
  • Uniform CORS, error envelopes and security checks across all functions
supabase/functions/create-job/index.ts
supabase/functions/get-job-status/index.ts
supabase/functions/update-job-step/index.ts
supabase/functions/create-job/deno.json
supabase/functions/get-job-status/deno.json
supabase/functions/update-job-step/deno.json
Add useJobNotifications hook for realtime workflow tracking
  • Subscribe to jobs and job_steps changes via Supabase channels
  • Maintain local jobs state, categorize active vs recent jobs
  • Show granular toasts for workflow start, running, step completion and final states
  • Compute progress percentages and update local cache on INSERT/UPDATE
frontend/src/hooks/use-job-notifications.tsx
Integrate realtime notifications and new JobMonitor UI
  • Dashboard.tsx: initialize useJobNotifications hook, update toast messages, remove redundant client-side job creation
  • Introduce JobMonitor component: displays cards with status badges, progress bar and cancellation
  • Provide a reusable Progress UI component and update package.json with @radix-ui/react-progress
frontend/src/pages/Dashboard.tsx
frontend/src/components/job-monitor.tsx
frontend/src/components/ui/progress.tsx
frontend/package.json
Encapsulate job operations in JobService
  • CreateJobRequest mapping to Edge Function payload
  • Implement createJob, getUserJobs, getJobWithSteps, updateJobStepByName and cancelJob via supabase.functions.invoke
  • Retain legacy direct Supabase methods for backward compatibility
frontend/src/services/jobService.ts
Document n8n integration for job orchestration
  • Provide a step-by-step guide for HTTP nodes to create jobs and update steps
  • Include error-handler path, branch logic and example Code Node helper
  • List best practices, environment variables and monitoring tips
docs/n8n-job-notifications-integration.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@vercel
Copy link
Copy Markdown

vercel Bot commented Aug 19, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
mindley-frontend Ready Ready Preview Comment Sep 4, 2025 10:45pm

@aintnier aintnier requested a review from Copilot August 19, 2025 22:09
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

Comment on lines +187 to +188
curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/get-job-status' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (curl-auth-header): Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.

Source: gitleaks

2. Make an HTTP request:

curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/get-job-status' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (jwt): Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

Source: gitleaks

Comment on lines +328 to +329
curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/update-job-step' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (curl-auth-header): Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.

Source: gitleaks

2. Make an HTTP request:

curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/update-job-step' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (jwt): Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

Source: gitleaks

This comment was marked as outdated.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a comprehensive job orchestration system that enables end-to-end workflow tracking for resource processing. The implementation provides real-time progress notifications, integrates with n8n workflows, and establishes a robust backend infrastructure for managing multi-step processing pipelines.

Key changes include:

  • Added job and job_steps database tables with corresponding Supabase Edge Functions for lifecycle management
  • Implemented real-time UI notifications system with progress tracking and toast notifications
  • Created n8n workflow integration with proper error handling and execution correlation

Reviewed Changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
supabase/functions/create-job/index.ts New Edge Function for job creation with user authentication and step initialization
supabase/functions/update-job-step/index.ts New Edge Function for step status updates with automatic job status aggregation
supabase/functions/get-job-status/index.ts New Edge Function for retrieving job status and progress information
frontend/src/hooks/use-job-notifications.tsx Real-time subscription hook for job and step notifications with toast integration
frontend/src/components/job-monitor.tsx UI component for displaying job status and progress with Italian localization
frontend/src/services/jobService.ts Service layer for job-related API calls and data management
frontend/src/types/job.ts TypeScript type definitions for job entities and related interfaces

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

const nowIso = new Date().toISOString()
updateData.completed_at = nowIso
// If step jumped directly from pending -> terminal without a running phase, also set started_at
updateData.started_at = updateData.started_at || nowIso
Copy link

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line attempts to set started_at on updateData, but updateData.started_at is not defined at this point, so the fallback will always execute. Consider checking if the step already has a started_at value from the database instead.

Suggested change
updateData.started_at = updateData.started_at || nowIso
updateData.started_at = currentStep?.started_at || nowIso

Copilot uses AI. Check for mistakes.
const limit = parseInt(url.searchParams.get('limit') || '10')
const status = url.searchParams.get('status')

if (jobId) {
Copy link

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment is unnecessary since jobIdParam could be used directly in the conditional check below.

Suggested change
if (jobId) {
const limit = parseInt(url.searchParams.get('limit') || '10')
const status = url.searchParams.get('status')
if (jobIdParam) {

Copilot uses AI. Check for mistakes.
Authorization: `Bearer ${session.access_token}`,
}
});

Copy link

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name should not include query parameters. Query parameters should be passed separately or the URL should be constructed properly using the base function name.

Suggested change
// Pass jobId as a custom header instead of query parameter
const { data, error } = await supabase.functions.invoke('get-job-status', {
method: 'GET',
headers: {
Authorization: `Bearer ${session.access_token}`,
'x-job-id': jobId,
}
});

Copilot uses AI. Check for mistakes.
<DropdownMenuContent>
<DropdownMenuItem onClick={() => onCancel(job.id)}>
Annulla Workflow
</DropdownMenuItem>
Copy link

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Mixed language usage - Italian text 'Annulla Workflow' in a component that has other English text. Consider using consistent localization throughout the component.

Suggested change
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onCancel(job.id)}>
Cancel Workflow
</DropdownMenuItem>

Copilot uses AI. Check for mistakes.
…rting newest/oldest to use processed_at timestampt instead of created_at timestamp; use-job-notifications realtime subscription configuration not properly working; add-resource form input placeholder changed to 'Resource Link'; failed workflow toast (destructive) is now the last toast that appears impeding failed steps toasts to display; create-job supabase function to fetch user email using userList as getUserByEmail is not supported. feat: added --success color and toast variant and utilized it for successful workflow toast.
…s fallback; minor UI issues for mobile screens; handling of svg icons, they now have their own component file
…ions to handle already available records from database
@aintnier aintnier merged commit c3c7569 into main Sep 4, 2025
6 checks passed
@aintnier aintnier deleted the fix/n8n-workflow-optimization branch September 4, 2025 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants